package net.xuej.swfbuilder{
	import flash.display.BitmapData;
	import flash.display.BitmapEncodingColorSpace;
	import flash.display.JPEGEncoderOptions;
	import flash.display.JPEGXREncoderOptions;
	import flash.display.PNGEncoderOptions;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	
	import org.as3commons.bytecode.abc.AbcFile;
	import org.as3commons.bytecode.abc.enum.Opcode;
	import org.as3commons.bytecode.emit.IClassBuilder;
	import org.as3commons.bytecode.emit.ICtorBuilder;
	import org.as3commons.bytecode.emit.IPackageBuilder;
	import org.as3commons.bytecode.emit.impl.AbcBuilder;
	import org.as3commons.bytecode.io.AbcSerializer;
	import org.libspark.swfassist.inprogress.swf.ShowFrameCounter;
	import org.libspark.swfassist.io.ByteArrayInputStream;
	import org.libspark.swfassist.io.DataInput;
	import org.libspark.swfassist.swf.io.ReadingContext;
	import org.libspark.swfassist.swf.io.SWFReader;
	import org.libspark.swfassist.swf.structures.Asset;
	import org.libspark.swfassist.swf.structures.FillStyle;
	import org.libspark.swfassist.swf.structures.FillStyleTypeConstants;
	import org.libspark.swfassist.swf.structures.RGB;
	import org.libspark.swfassist.swf.structures.SWF;
	import org.libspark.swfassist.swf.structures.StraightEdgeRecord;
	import org.libspark.swfassist.swf.structures.StyleChangeRecord;
	import org.libspark.swfassist.swf.tags.DefineBits;
	import org.libspark.swfassist.swf.tags.DefineBitsJPEG2;
	import org.libspark.swfassist.swf.tags.DefineBitsJPEG3;
	import org.libspark.swfassist.swf.tags.DefineShape;
	import org.libspark.swfassist.swf.tags.DefineSprite;
	import org.libspark.swfassist.swf.tags.DoABC;
	import org.libspark.swfassist.swf.tags.PlaceObject2;
	import org.libspark.swfassist.swf.tags.RemoveObject;
	import org.libspark.swfassist.swf.tags.SetBackgroundColor;
	import org.libspark.swfassist.swf.tags.ShowFrame;
	import org.libspark.swfassist.swf.tags.SymbolClass;
	import org.libspark.swfassist.swf.tags.Tag;
	import org.libspark.swfassist.swf.tags.TagVisitor;

	/**
	 * tag 创建器
	 * @author xuej
	 * 
	 */
	public class TagsBuilder{
		/**
		 * tag 创建器
		 * 
		 */
		public function TagsBuilder(){
			
		}
		
		/**
		 * 创建doabc 目前只支持 BitmapData
		 * @param classNameDic
		 * @return 
		 * 
		 */
		public static function createDoABCTag(linkArr:Vector.<LinkInfo>):Tag{
			var ab:AbcBuilder = new AbcBuilder();
			var pb:IPackageBuilder = ab.definePackage("");
			for each(var link:LinkInfo in linkArr){
				var cb:IClassBuilder = pb.defineClass(link.name,link.className);
				cb.isDynamic = true;
				var ctorBuilder:ICtorBuilder = cb.defineConstructor()
				ctorBuilder.defineArgument("int", true, 54);
				ctorBuilder.defineArgument("int", true, 44);
				ctorBuilder.addOpcode(Opcode.getlocal_0)
					.addOpcode(Opcode.pushscope)
					.addOpcode(Opcode.getlocal_0)
					.addOpcode(Opcode.getlocal_1)
					.addOpcode(Opcode.getlocal_2)
					.addOpcode(Opcode.constructsuper, [2])
					.addOpcode(Opcode.returnvoid);
			}
			var af:AbcFile = ab.build();
			var asl:AbcSerializer =new AbcSerializer();
			var abc:DoABC = new DoABC();
			abc.name = "doabc";
			abc.abcData = asl.serializeAbcFile(af);
			return abc;
		}
		
		/**
		 * 创建SymbolClass Tag
		 * @param symbols dictionary:[{id1:className1},{id2:className2}...]
		 * @return 
		 * 
		 */
		public static function createSymbolClass(linkArr:Vector.<LinkInfo>):Tag{
			var sbc:SymbolClass = new SymbolClass();
			sbc.symbols = new Array();
			for each(var link:LinkInfo in linkArr){
				var asset:Asset = new Asset();
				asset.characterId = link.index;
				asset.name = link.name;
				sbc.symbols.push(asset);
			}
			return sbc;
		}
		
		/**
		 * 创建背景颜色
		 * @param color
		 * @return 
		 * 
		 */
		public static function createBackgroundColorTag(color:uint = 0xffffff):Tag{
			var bgTag:SetBackgroundColor = new SetBackgroundColor();
			var rgb:RGB = new RGB();
			rgb.fromUint(color);
			bgTag.backgroundColor = rgb;
			return bgTag;
		}
		
		/**
		 * 创建ShowframeTag
		 * @return 
		 * 
		 */
		public static function createShowFrameTag():Tag{
			var sf:ShowFrame = new ShowFrame();
			return sf;
		}
		
		
		
		/**
		 * 创建图片tag
		 * @param bitmapData
		 * @param quality
		 * @param className
		 * 
		 */
		public static function createImageTag(id:int,bitmapData:BitmapData,quality:int,encoderType:String=ImgEncodeType.JPEG):Tag{
			var it:DefineBits;
			var b1:ByteArray = getAlpha(bitmapData);
			if(b1 != null){
				b1.compress();
				it = new DefineBitsJPEG3();
				(it as DefineBitsJPEG3).bitmapAlphaData = b1;
			}else{
				it = new DefineBitsJPEG2();
			}
			it.characterId = id;
			var b:ByteArray = new ByteArray();
			switch(encoderType){
				case ImgEncodeType.JPEG:
					bitmapData.encode(bitmapData.rect,new JPEGEncoderOptions(quality),b);
					break;
				case ImgEncodeType.JPEG_XR:
					bitmapData.encode(bitmapData.rect,new JPEGXREncoderOptions((100-quality),BitmapEncodingColorSpace.COLORSPACE_4_2_0),b);
					break;
				case ImgEncodeType.PNG:
					bitmapData.encode(bitmapData.rect,new PNGEncoderOptions(),b);
					break;
			}
			
			it.jpegData = b;
			return it;
		}
		
		/**
		 * 创建原始图片tag
		 * @param id
		 * @param byteArray
		 * @return 
		 * 
		 */
		public static function createOriImageTag(id:int,byteArray:ByteArray):Tag{
			var dbj:DefineBitsJPEG2 = new DefineBitsJPEG2();
			dbj.characterId = id;
			dbj.jpegData = byteArray;
			return dbj;
		}
		
		/**
		 * 创建swf tag
		 * @param index
		 * @param byteArray
		 * @return 
		 * 
		 */
		public static function createSwfTag(index:int, byteArray:ByteArray):Tag{
			var sr:SWFReader = new SWFReader();
			var di:DataInput = new ByteArrayInputStream(byteArray);
			var context:ReadingContext = new ReadingContext();
			context.needsABCData = true;
			var swf:SWF = sr.readSWF(di,context);
			var visitor:ShowFrameCounter = new ShowFrameCounter();
			swf.visit(visitor);
			var dsp:DefineSprite = new DefineSprite();
			dsp.spriteId = index;
			dsp.numFrames = visitor.numFrames;
			dsp.tags = swf.tags;			
			return dsp;
		}
		
		/**
		 * 创建placeObject tag
		 * @param index
		 * @param depth
		 * @return 
		 * 
		 */
		public static function createPlaceObject(index:int,depth:int):Tag{
			var po:PlaceObject2 = new PlaceObject2();
			po.hasCharacter = true;
			po.hasMatrix = true;
			po.depth= depth;
			po.characterId = index;
			return po;
		}
		
		/**
		 * 创建removeObject tag
		 * @param index
		 * @param depth
		 * @return 
		 * 
		 */
		public static function createRemoveObject(index:int,depth:int):Tag{
			var ro:RemoveObject = new RemoveObject();
			ro.characterId = index;
			ro.depth = depth;
			return ro;
		}
		
		/**
		 * 创建 shape tag
		 * @param index
		 * @param bitmapIndex
		 * @param width
		 * @param height
		 * @param x
		 * @param y
		 * @return 
		 * 
		 */
		public static function createShape(index:int,bitmapIndex:int,width:int,height:int,x:int,y:int):Tag{
			var r1:StyleChangeRecord = new StyleChangeRecord();
			r1.stateFillStyle0 = true;
			r1.stateMoveTo = true;
			r1.fillStyle0 = 1;
			r1.moveDeltaX = x;
			r1.moveDeltaY = y;
			var r2:StraightEdgeRecord = new StraightEdgeRecord();
			r2.verticalLine = true;
			r2.deltaY = height;
			var r3:StraightEdgeRecord = new StraightEdgeRecord();
			r3.horizontalLine = true;
			r3.deltaX = width;
			var r4:StraightEdgeRecord = new StraightEdgeRecord();
			r4.verticalLine = true;
			r4.deltaY = -height;
			var r5:StraightEdgeRecord = new StraightEdgeRecord();
			r5.horizontalLine = true;
			r5.deltaX = -width;
			
			var tagFS:FillStyle = new FillStyle();
			tagFS.color.fromUint(0xff000000);
			tagFS.fillStyleType = FillStyleTypeConstants.NON_SMOOTHED_CLIPPED_BITMAP;
			tagFS.bitmapId = bitmapIndex;
			tagFS.bitmapMatrix.hasScale = true;
			tagFS.bitmapMatrix.scaleX = 20;//(20twip = 1px)
			tagFS.bitmapMatrix.scaleY = 20;
			tagFS.bitmapMatrix.translateX = x;
			tagFS.bitmapMatrix.translateY = y;
			
			var tagDS:DefineShape = new DefineShape();
			tagDS.shapeId = index;
			tagDS.shapeBounds.xMin = x;
			tagDS.shapeBounds.xMax = width + x;
			tagDS.shapeBounds.yMin = y;
			tagDS.shapeBounds.yMax = height + y;
			tagDS.shapes.shapeRecords = [r1,r2,r3,r4,r5];
			tagDS.shapes.fillStyles.fillStyles = [tagFS];
			
			return tagDS;
		}
		
		/**
		 * 获得图片的alpha通道bytearray
		 * @param _bmd
		 * @return 
		 * 
		 */
		private static function getAlpha(_bmd:BitmapData):ByteArray{
			var aba:ByteArray = new ByteArray();
			var hasAlpha:Boolean = false;
			for(var i:int=0;i<_bmd.height;i++){
				for(var j:int=0;j<_bmd.width;j++){
					var _pixel:int = _bmd.getPixel32(j,i);
					var _alpha:int = _pixel >> 24 & 0xFF;
					if(_alpha != 255){
						hasAlpha = true;
					}
					aba.writeByte(_alpha);
				}
			}
			if(!hasAlpha){
				aba.clear();
				aba = null;
			}
			return aba;
		}
	}
}